import Watcher from "./observe/watcher.js";
import { createElement, createNodeText } from "./vdom/create-element.js";

export function initLifeCycle(Vue) {
  //创建节点
  Vue.prototype._c = function () {
    return createElement(this, ...arguments);
  };
  //创建文本节点
  Vue.prototype._v = function (text) {
    return createNodeText(this, text);
  };
  //转换为字符串
  Vue.prototype._s = function (val) {
    return val === null
      ? ""
      : typeof val === "object"
      ? JSON.stringify(val)
      : val;
  };

  Vue.prototype._update = function (vnode) {
    const vm = this;
    const el = vm.$el;
    vm.$el = path(el, vnode);
  };

  //render方法将模板编译为虚拟dom
  Vue.prototype._render = function () {
    const vm = this;
    const { render } = vm.$options;
    //执行
    let node = render.call(vm);
    return node;
  };
}

//创建真实
function createRealElement(vnode) {
  const { tag, data, children, text } = vnode;
  if (tag && typeof tag === "string") {
    //创建标签
    vnode.el = document.createElement(tag);
    //处理属性
    pathProps(vnode.el, data);
    //递归创建子节点
    children.forEach((child) => {
      vnode.el.appendChild(createRealElement(child));
    });
  } else {
    //创建文本
    vnode.el = document.createTextNode(text);
  }
  return vnode.el;
}

//处理属性
function pathProps(el, data) {
  if (!data) return;
  for (let key in data) {
    if (key === "style") {
      for (let styleName in data.style) {
        el.style[styleName] = data.style[styleName];
      }
    } else {
      el.setAttribute(key, data[key]);
    }
  }
}

//处理节点
function path(el, vnode) {
  console.log(el, vnode);
  const isRealElement = el.nodeType;
  if (isRealElement) {
    //真实dom
    const parentElement = el.parentNode;
    const newElem = createRealElement(vnode);
    parentElement.insertBefore(newElem, el.nextSibling);
    parentElement.removeChild(el);
    return newElem;
  } else {
    //diff算法
  }
}

// vue的核心流程 1）创建了响应式数据 2）模板转换成ast语法树 3）ast语法树生成render函数 4）生成虚拟dom 5）生成真实dom
export function mountComponent(vm, el) {
  vm.$el = el; //挂载到实例上
  //1.调用render方法，生成虚拟dom //2.将虚拟dom生成真实dom //3.将真实dom插入el中
  // const vnode = vm._render();
  // vm._update(vnode);

  // 通过watcher来渲染
  const updateComponent = () => {
    vm._update(vm._render());
  };
  console.log("updateComponent", vm._render);
  new Watcher(vm, updateComponent);
}

// 调用生命周期
export function callHook(vm, hook) {
  const handlers = vm.$options[hook];
  if (handlers) {
    handlers.forEach((handler) => handler.call(vm));
  }
}
